package rabbitmq

import (
	"context"
	"fmt"
	"portal_mq/global"
	"time"

	amqp "github.com/rabbitmq/amqp091-go"
	"go.uber.org/zap"
)

func NewRabbitMQTopicProducer(opts *RabbitOptions) *RabbitMQ {
	mq := &RabbitMQ{
		QueueName:    opts.QueueName,
		ExchangeName: opts.ExchangeName,
		BindingKey:   opts.BindingKey,
	}

	// dial
	var err error
	rabbitURL := fmt.Sprintf("amqp://%s:%s@%s:%d/", global.ServiceConfig.RabbitMQ.Username, global.ServiceConfig.RabbitMQ.Password, global.ServiceConfig.RabbitMQ.Host, global.ServiceConfig.RabbitMQ.Port)
	mq.conn, err = amqp.Dial(rabbitURL)
	if err != nil {
		zap.L().Error("Failed to connect to RabbitMQ", zap.Error(err))
		return nil
	}

	// get channel
	mq.channel, err = mq.conn.Channel()
	if err != nil {
		zap.L().Error("Failed to create channel", zap.Error(err))
		return nil
	}

	// exchange declare
	err = mq.channel.ExchangeDeclare(
		mq.ExchangeName,
		"topic",
		true,  // durable
		false, // auto delete
		false, // internal
		false, // no wait
		nil,   // arguments
	)
	if err != nil {
		zap.L().Error("Failed to declare exchange", zap.Error(err))
		return nil
	}

	return mq
}

func (r *RabbitMQ) Publish(message string) error {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()
	err := r.channel.PublishWithContext(
		ctx,
		r.ExchangeName,
		r.BindingKey,
		false,
		false,
		amqp.Publishing{
			ContentType: "application/json",
			Body:        []byte(message),
		},
	)
	return err
}

func (r *RabbitMQ) Close() {
	r.channel.Close()
	r.conn.Close()
}
